package com.jenvin.idcreator;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 单例化 IdCreator 必须单列的形式注入到spring
 * 
 * @author jenvin 2012-4-14 下午11:38:22
 */
public class CopyOfIdCreator {

    private final static long DEFAULT_L1_BUFFER_SIZE = 950;
    private final static long DEFAULT_L2_BUFFER_SIZE = 50;
    private long              l1BufferSize           = DEFAULT_L1_BUFFER_SIZE;
    private long              l2BufferSize           = DEFAULT_L2_BUFFER_SIZE;
    private IdCreatorProvider provider               = null;
    private AtomicLong        offerset               = null;
    private volatile long     threshold              = 0;
    private long              seed                   = 0;
    private String            name                   = "";
    private String            description            = "";
    private Object            locker                 = new Object();

    public void setL1BufferSize(long l1BufferSize) {
        this.l1BufferSize = l1BufferSize;
    }

    public void setL2BufferSize(long l2BufferSize) {
        this.l2BufferSize = l2BufferSize;
    }

    public long getNewId() {
        if (offerset == null) {
            synchronized (locker) {
                if (offerset == null) {
                    long start = provider.aquireIdBuffer(l1BufferSize, seed, name, description);
                    offerset = new AtomicLong(start + 1);
                    threshold = start + l1BufferSize;
                }
            }
        } else if (offerset.get() > threshold - l2BufferSize) {
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    long start = provider.aquireIdBuffer(l1BufferSize, seed, name, description);
                    offerset = new AtomicLong(start + 1);
                    threshold = start + l1BufferSize;
                    locker.notifyAll();
                }
            });
            thread.start();
        } else if (offerset.get() > threshold) {
            try {
                locker.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return offerset.getAndIncrement();
    }

    public long getSeed() {
        return seed;
    }

    public void setSeed(long seed) {
        this.seed = seed;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public void setProvider(IdCreatorProvider provider) {
        this.provider = provider;
    }

    public IdCreatorProvider getProvider() {
        return provider;
    }
}
